/* 	File		: IOGame.h
 *	Nama penanggunag jawab	: Ahmad Anshorimuslim Syuhada
 * 	NIM			: 13509064
 * 	Deskripsi	: Reallisasi class IO
*/

#include "IOGame.h"
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
#include <dirent.h>

using namespace std;
using std::ifstream;
using std::ofstream;

/* Konstruktor */	
IOGame::IOGame(){
}
		
IOGame::IOGame(const string& namafile){
		namaf=namafile;
}
	
/* Destruktor */	
IOGame::~IOGame(){
		namaf="";
		folder="";
}
			
/* Other Method */	
string IOGame::GetName(){
		return namaf;
}
	
void IOGame::SetName(string namafile) {
		namaf=namafile;
}
	
string IOGame::GetFolder(){
		return folder;
}
	
void IOGame::SetFolder(){	//mensetfolder dengan membuka browser dialog
    BROWSEINFO   bi;  //objek dari winAPI
    ZeroMemory(&bi,   sizeof(bi)); 
    TCHAR   szDisplayName[MAX_PATH]; //menyimpan alamat path
    //szDisplayName[0]    =   ''";  

    bi.hwndOwner        =   NULL; 
    bi.pidlRoot         =   NULL; 
    bi.pszDisplayName   =   szDisplayName; 
    //bi.lpszTitle        =   _T("Please select a folder for storing received files :"); 	//belum jelas
    bi.ulFlags          =   BIF_RETURNONLYFSDIRS;
    //bi.lParam           =   NULL;  //belum jelas
    bi.iImage           =   0;  

    LPITEMIDLIST   pidl   =   SHBrowseForFolder(&bi); //membuka browse folder dialog
    TCHAR   szPathName[MAX_PATH]; 
    if   (NULL   !=   pidl)
    {
         BOOL bRet = SHGetPathFromIDList(pidl,szPathName); //mengambil path item
         if(FALSE == bRet)
              return;
        // AfxMessageBox(szPathName);
		//std::cout << szPathName;
    }			
	
	folder=szPathName;
}
	
void IOGame::OpenFarm(Player* org, waktu* tm, AllMap* am, string namafile){
	ifstream input;

	input.open(namafile.c_str()); //membuka file
	if(!input) // mengecek hasil pembukaan file
	{
		cerr << "File tidak bisa dibuka.\n"; //print 'cannot open file'
	} else
	{		
		LoadPetak(&input, am);
		
		LoadWaktu(&input, tm);
		
		LoadTanam(&input, am);
		
		LoadPlayer(&input, org);
			
		getch();
		//menutup file
		input.close();
	}
}

void IOGame::LoadPetak(ifstream* input, AllMap* am){
	string ch;
	string h;
	int i,j;
	int p,pe,pa,c,s;
	
	for (i=6; i>=0; i--){ //membaca data lahan 6*7 petak
			for (j=0; j<=5; j++){
				(*input)>>ch; //mengambil satu panjang string sebelum samapai spasi
				h=ch[0]; //mencacah string -> char* //plantable
				p=atoi(h.c_str()); //memasukkan ke penampung sementara, berupa integer
				h=ch[1];	//plantexist
				pe=atoi(h.c_str()); //cout<<ch<<endl; getch();
				h=ch[2];	//plantalive
				pa=atoi(h.c_str());
				h=ch[3];	//iscangkul
				c=atoi(h.c_str());
				h=ch[4];	//issiram
				s=atoi(h.c_str());
				//cout<<ch<<" ";
				(*am).SetLFieldXY(j,i,p,pe,pa,c,s);
				// SetLFieldXY			(int x, int y, int P, int PE, int PA, int C, int S);
			}
			//cout<<endl; getch();
	} //membaca lahan
}
void IOGame::LoadWaktu(ifstream* input, waktu* tm){
	int hh,bb,mu,jj,mm;
	
	(*input)>>hh;
	(*tm).SetHH(hh);
	
	(*input)>>bb;
	(*tm).SetBB(bb);
	
	(*input)>>mu;
	(*tm).SetMU(mu);
	
	(*input)>>jj;
	(*tm).SetJJ(jj);
	
	(*input)>>mm;
	(*tm).SetMM(mm);
	
	// cout<<hh<<"-"<<bb<<"-"<<mu<<"-"<<jj<<"-"<<mm<<endl; getch();
}

void IOGame::LoadTanam(ifstream* input, AllMap* am){
	int i,j;
	int id,um,hp;
	
	i=6;
	while (i>=0){
		 j=0;
		 while (j<=5){
			(*input)>>id; //cout<<id;
			(*am).GetLFieldXY(j,i)->KerjaPaksa(id); //ini caranya untuk meload objek tanaman ke petak
			
			(*input)>>um; //cout<<um;
			(*am).GetLFieldXY(j,i)->GetPlant()->setUmur(um);//men set umur
			
			(*input)>>hp; //cout<<hp<<" ";
			(*am).GetLFieldXY(j,i)->GetPlant()->setHappyMeter(hp);//men set happy
			j++; //INCR absis
		}
		// cout<<endl; getch();
		i--; //DCR ordinat
	}
}
void IOGame::LoadPlayer(ifstream* input, Player* org){
	string nm;
	int od,sw,ug,s1,a1,s2,a2,s3,a3;
	
	//membaca nama
	(*input)>>nm;
	(*org).setName(nm);
	//cout<<nm<<endl;
	
	//membaca status meter
	(*input)>>od;
	(*org).setOD(od); //ODmeter
	(*input)>>sw;
	(*org).setSakaw(sw); //sakawmeter
	//cout<<od<<" "<<sw<<endl;
	
	//membaca uang, 
	(*input)>>ug;
	(*org).setMoney(ug);
	//cout<<ug<<endl;
	
	//memasukkan inventory
	(*input)>>s1; //1
	(*org).getInventory()->setSlot1(KonvInv(s1)); //jenis barang di slot

	(*input)>>a1;
	(*org).getInventory()->setAmount1(a1); //kuantitas barang

	(*input)>>s2; //2
	(*org).getInventory()->setSlot2(KonvInv(s2));

	(*input)>>a2;
	(*org).getInventory()->setAmount2(a2);

	(*input)>>s3; //3
	(*org).getInventory()->setSlot3(KonvInv(s3));

	(*input)>>a3;
	(*org).getInventory()->setAmount3(a3);
	// cout<<s1<<" "<<a1<<endl;
	// cout<<s2<<" "<<a2<<endl;
	// cout<<s3<<" "<<a3<<endl;
}

void IOGame::SaveFarm(Player* org, waktu* tm, AllMap* am, string namafile){
    ofstream output(namafile.c_str()); //membuat file save
	if(!output) // jika gagal membuat (dan membuka) file
	{
		cerr << "Tidak dapat membuat file penyimpanan.\n"; //pesan error
	} else {
		//KAMUS
		int i,j,temp;
		int p,pe,pa,c,s;
		char *ch;
		string kt;
		
		//ALGORITMA
		for (i=6; i>=0; i--){ //menuliskan data petak lahan sesuai struktur
			for (j=0; j<=5; j++){ 	//ambil semua IsPlantExist, IsPlantAlive, IsCangkul, IsSiram
				temp=(*am).GetLFieldXY(j,i)->IsPlantable();				//"plantable="
				output<<temp;
				temp=(*am).GetLFieldXY(j,i)->IsPlantExist();				//"plantexist="
				output<<temp;
				temp=(*am).GetLFieldXY(j,i)->IsPlantAlive();				//"plantalive="
				output<<temp;
				temp=(*am).GetLFieldXY(j,i)->IsCangkul();				//"cangkul="
				output<<temp;
				temp=(*am).GetLFieldXY(j,i)->IsSiram();				//"siram="
				output<<temp<<" ";
			}
			output<<endl;
		} //menulis lahan
		
		//menulis waktu,
		//"curr_waktu=";
		temp=(*tm).GetHH(); output<<temp<<" "; //hari
		temp=(*tm).GetBB(); output<<temp<<" "; //bulan
		temp=(*tm).GetMU(); output<<temp<<" "; //musim
		temp=(*tm).GetJJ(); output<<temp<<" "; //jam
		temp=(*tm).GetMM(); output<<temp<<endl; //menit
				
		for (i=6; i>=0; i--){ 
			for (j=0; j<=5; j++){ 
				temp=(((*am).GetLFieldXY(j,i))->GetPlant())->getID(); 				//"id=";
				output<<temp<<" ";
				temp=(*am).GetLFieldXY(j,i)->GetPlant()->getUmur();				//"umur=";
				output<<temp<<" ";
				temp=(*am).GetLFieldXY(j,i)->GetPlant()->getHappyMeter();				//"happy=";
				output<<temp<<" ";
			}
			output<<endl;
		} //menulis prop tanaman
		
		//menulis nama
		//"nama=";
		kt=(*org).getName(); output<<kt<<endl;
		
		//menulis status meter,
		//"od_meter=";
		temp=(*org).getOD(); output<<temp<<" ";
		//"sakaw_meter=";
		temp=(*org).getSakaw(); output<<temp<<endl;
		
		//"uang=";
		temp=(*org).getMoney(); output<<temp<<endl;
		
			//"jenis=";
		temp=(*org).getInventory()->getSlot1()->getID(); output<<temp<<" ";	//1
			//"kuantitas=";
		temp=(*org).getInventory()->getAmount1(); output<<temp<<endl;
			//"jenis=";
		temp=(*org).getInventory()->getSlot2()->getID(); output<<temp<<" ";	//2
			//"kuantitas=";
		temp=(*org).getInventory()->getAmount2(); output<<temp<<endl;
			//"jenis=";
		temp=(*org).getInventory()->getSlot3()->getID(); output<<temp<<" ";	//3
			//"kuantitas=";
		temp=(*org).getInventory()->getAmount3(); output<<temp<<endl;
			
		//} //membaca inventory
		output<<"#";	//memberi tanda akhir
		output.close();	//menutup stream file
		SetName(namafile);
	}
}
	
void IOGame::SaveFarmE(Player* org, waktu* tm, AllMap* am){	//prompt awal menyimpan file
		string s=GetName();	//mengecek atribut nama file di objek
		if (s.compare("")==0){ //berarti tidak ada di objek IO namafile-nya
			string name;
			string add=".txt";	//tambahan ekstensi file
				//string name = BrowseFile(false); //Membuka browse dialog
				//cout<<endl<<"Pilih lokasi folder penyimpanan :"<<endl;
				//SetFolder();
			cout<<".::DAFTAR FILE::."<<endl;
			ListFile();	//prosedur me-list file yang ada setingkat direktori eksekusi perintah
			cout<<endl<<"Masukkan nama file yang ingin disimpan :"<<endl;
			cout<<"Nama file : "; cin>>name;	//minta input nama fle, tidak perlu nama ekstensi
			name.append(add, 0, add.size());	//menambahkan ekstensi ke nama file
			ifstream tes;
			tes.open(name.c_str());	//mentes apakah bisa membuka file
			
			if(tes){	//memeriksa apakh file sudaha da
				cerr<<"File sudah ada"<<endl;
				cout<<"Ingin menindih yang lama(y/~))?";	//prompt apakah ingin menindih file
				char p;
				cin>>p;
				if ((int(p)==89)||(int(p)==121)){	//apakah pilihan  'y' atau 'Y'
					SaveFarm(org, tm, am, name);	//menyimpan file
				}else{
					cout<<"Penyimpanan dibatalkan"<<endl;
					tes.close();
				}
				
			}else{
				SaveFarm(org, tm, am, name); //menyimpan dengan nama file baru
			}
		}else{
			SaveFarm(org, tm, am, GetName()); //menyimpan dengan nama file terdahulu
		 }
}

	
	
void IOGame::OpenMap(AllMap* am){	//membuka data map statik permainan
	ifstream input;

	input.open("../map/map.txt");	//alamat map
	if(!input) // jika gagal dan membuka file
	{
		cerr << "File tidak dapat dibuka.\n"; //pesan error
	} else
	{		
		int i,j,temp;
		int m,s,b,jp,t;
		string tk, rmh, lh;
		string h;
		
		//m::0=extra, 1=rumah 2=toko
		for (i=2; i>=0; i--){
			for (j=0; j<=2; j++){
				input>>tk;	//mengambil satu kata penuh samapi spasi
				h=tk[0];
				s=atoi(h.c_str());	//saveable
				h=tk[1];
				b=atoi(h.c_str());	//buyable
				h=tk[2];
				jp=atoi(h.c_str());	//sellable
				h=tk[3];
				t=atoi(h.c_str());	//sleepable
				(*am).SetNLFieldXY(2,j,i,s,b,jp,t);	//menset petak
			}
		} //membaca toko
		
		for (i=2; i>=0; i--){
			for (j=0; j<=2; j++){
				input>>rmh; 
				h=rmh[0];
				s=atoi(h.c_str());	//mengambil satu kata penuh samapi spasi
				h=rmh[1];
				b=atoi(h.c_str());	//saveable
				h=rmh[2];
				jp=atoi(h.c_str());	//buyable
				h=rmh[3];
				t=atoi(h.c_str());	//sleepable
				(*am).SetNLFieldXY(1,j,i,s,b,jp,t);	//menset petak
			}
		} //membaca rumah
		
		//extensi lahan
		for (i=0; i<=5; i++){
			input>>lh; 
			h=lh[0];
			s=atoi(h.c_str());	//mengambil satu kata penuh samapi spasi
			h=lh[1];
			b=atoi(h.c_str());	//saveable
			h=lh[2];
			jp=atoi(h.c_str());	//buyable
			h=lh[3];
			t=atoi(h.c_str());	//sleepable
			(*am).SetNLFieldXY(0,i,7,s,b,jp,t);	//menset petak
		}
		//menutup stream file
		input.close();
	}
}
	
	/*string IOGame::BrowseFile(bool isOpen){
		//SOMETHING code's here
	}*/

	// void IOGame::SearchFile(string namafile, bool& tes){	//mencari keberadaan file
	// //true jika file sudaha ada, false jika belum ada
		// try{	//exception handling
			// ifstream coba;
			// coba.open(namafile.c_str());	//membuka file
			// if (!tes){
				// throw (char*) "File tidak ada";
				// tes=false;
			// }else{
				// coba.close();	//menutup stream file
				// tes=true;
			// }
		// }
		// catch(char* err){
			// cout<<"Error caught : "<<err<<endl;	//pesan error
		// }
		
	// }
	
void IOGame::ListFile(){	//me-list seluruh file di level direktori berada
		DIR *pDIR;	//objek direktori
        struct dirent *entry;	//membuat struct menyimpan nama file
        if( pDIR=opendir(".") ){ //alamat folder
                while(entry = readdir(pDIR)){	//selama masih ada file di direktori yang belum terbaca
                        if( strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0 )	//tidak memasukkan .=direktori tsb, ..=up level dir
                        cout << "\n" <<entry->d_name;	//melist file
                }
				cout<<"\n\n>-SELESAI MEMBACA ISI FOLDER-<\n\n";
                closedir(pDIR);	//menutup direktori pembacaan
        }
}

Tanaman* IOGame::KonvInv(int ID){	//menghasilkan objek dari keterangan ID
	switch (ID){
		case 1 : { //kasus 1
			Ganja* ganja = new Ganja;
			return ganja;
			break;						
		}
		case 2: {	//kasus 2
			Opium* opium = new Opium;
			return opium;
			break;						
		}
		case 3: {	//kasus 3
			Coca* coca = new Coca;
			return coca;
			break;						
		}
		case 4 : {	//kasus 4
			Tobacco* tobacco = new Tobacco;
			return tobacco;
			break;						
		}
		case 5 : {	//kasus 5
			Anggur* anggur = new Anggur;
			return anggur;
			break;						
		}
		case 6 : {	//kasus 6
			Mushroom* mushroom = new Mushroom;
			return mushroom;
			break;						
		}
		
		default : {	//kasus stress
			Tanaman* tanaman = new Tanaman;
			return tanaman;
			break;						
		}
	}
}
